#ifndef _HOOK_PROC_MANAGER_H_
#define _HOOK_PROC_MANAGER_H_

#ifndef BOOST_BIND_ENABLE_STDCALL
#define BOOST_BIND_ENABLE_STDCALL
#endif

#include "Hook.h"
#include "HookProcLib.h"

#include <boost/shared_ptr.hpp>
#include <boost/ptr_container/ptr_set.hpp>

#include <string>
#include <list>
#include <functional>


namespace sd
{
namespace hp
{

namespace impl
{
class HookedProcessImplementation;
}


class HookedProcess
{

public:
	static HookedProcess& getInstance();

	template< typename TProc >
	Hook<TProc>& getHook( const std::string& name, const std::string& library );

	void lock();
	void unlock();
	bool isLocked();

	void setSoftDeactivateMode( bool mode ){ softDeactivateMode_ = mode; } // if this mode enabled - when hook is deactivated the hooked procedure call original proc, without changes in asm code
	bool getSoftDeactivateMode()const{ return softDeactivateMode_; }

	bool getAutolockingMode()const{ return autolockingMode_; } // auto lock process, when tryid to hook function
	void setAutolockingMode( bool mode ){ autolockingMode_=mode; }

	bool checkLockedThreadsActiveCode(const void*)const;



protected:	
	friend class HookBase;


	template< typename T, typename comparator >
	struct pls 
	{
		bool operator()( const T _Left, const T _Right) const{ return comparator()(*_Left, *_Right); }
	};

	//typedef boost::ptr_set< HookBase, std::less< HookBase > > Hooks;
	typedef std::set< HookBase*, pls< HookBase*, std::less< HookBase > > > Hooks;
	HookedProcess();
	//impl::HookImplementation* createHook( HookBase& );
	LibraryRef getLibrary( const std::string& name );

	Hooks::iterator findHook( const std::string& name, const std::string& library );

	template< typename TProc >
	Hook<TProc>&  createHook( const std::string& name, const std::string& library )
	{
		Hook<TProc>* hook = new Hook<TProc>( name, library );
		hooks_.insert( hook );
		return *hook;
	}

private:
	bool softDeactivateMode_;
	bool autolockingMode_;
	Hooks hooks_;
	impl::HookedProcessImplementation& impl_;
};

template< typename TProc >
Hook<TProc>& HookedProcess::getHook(const std::string& name, const std::string& library )
{
	Hooks::iterator it = findHook( name, library );
	if( it == hooks_.end() )
		return createHook<TProc>( name, library );
	else
		return *static_cast< Hook<TProc>* >( *it );
}














}
}
#endif//_HOOK_PROC_MANAGER_H_
